package com.cneport.das.server.trans.core;

import cn.hutool.crypto.digest.Digester;
import com.cneport.das.common.utils.DateUtil;
import com.cneport.das.common.utils.FileUtil;
import com.cneport.das.common.utils.JAXBUtils;
import com.cneport.das.common.utils.StringUtil;
import com.cneport.das.server.conf.ConfigCaches;
import com.cneport.das.server.trans.conf.Authen;
import com.cneport.das.server.trans.conf.Bindings;
import com.cneport.das.server.trans.conf.CorpInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Desc 客户端绑定相关的Service
 * @Ver 1.0
 * @Author GavinZhang
 * @Company 东方物通科技有限（北京）公司
 * @Date 2021-12-27 09:58:15
 */
@Service
@Slf4j
public class AuthCheckService {
    private static final Integer MAX_SEQ = 9999;
    @Autowired
    private ConfigCaches configCaches;
    /**
     * 登记的合法licence（若允许一个授权的客户端部署在多台机器上，即相当于一个licence有多个bindNo）
     */
    private Map<String, List<String>> exist = new ConcurrentHashMap<>();

    /**
     * 违反政策的corpNo
     */
    private List<String> violate = Collections.synchronizedList(new ArrayList());

    /**
     * 验证licence是否有效
     *
     * @param licence
     * @return
     */
    public synchronized boolean verify(String corpNo, String licence) {
        CorpInfo corpInfo = configCaches.getCorpInfoByCorpNo(corpNo);
        if (corpInfo == null) {
            return false;
        }
        if (!licence.equals(corpInfo.getLicence())) {
            return false;
        }
        if (violate.contains(corpNo)) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * 登记客户端信息
     *
     * @param ip
     * @param mac
     * @param corpNos
     */
    public synchronized void regist(String ip, String mac, List<String> corpNos) {
        Map<String, List<String>> corpBinds = configCaches.getCorpBinds();
        String bindingNo = "";
        for (String corpNo : corpNos) {
            bindingNo = genBindNo(ip, mac, corpNo);
            List<String> bindingnos = corpBinds.get(corpNo);
            //如果之前没有绑定配置文件，之间生成并绑定
            if (bindingnos == null) {
                bindingnos = new ArrayList<>();
            }

            //获取当前公司的绑定信息
            List<Bindings.Bind> binding = configCaches.getCorpBindsByCorpNo(corpNo);
            if (binding == null) {
                binding = new ArrayList<>();
            }


            //已经存在配置文件
            if (bindingnos.contains(bindingNo)) {
                //匹配绑定
                return;
            } else {
                //不匹配绑定
                int enable = configCaches.getEnableBinding();
                Authen entity = configCaches.getCorpAuthByCorpNo(corpNo);
                if (entity == null) {
                    //主配置没有，不做绑定
                    continue;
                }
                int clients = entity.getAllowNum();
                //启用
                if (enable == 1 && clients > 0) {
                    //少于允许的绑定数
                    if (bindingnos.size() < clients) {
                        //加入缓存
                        bindingnos.add(bindingNo);

                        //写入配置文件
                        if (binding.size() == 0) {
                            binding.addAll(Arrays.asList(Bindings.Bind.builder().bindingNo(bindingNo).createAt(DateUtil.C14()).isDel(0).gid("0001").build()));
                        } else {
                            List<Bindings.Bind> binds = binding;
                            Bindings.Bind last = binds.get(binds.size() - 1);
                            String guid = last.getGid();
                            Integer l = Integer.parseInt(guid);
                            int id = l + 1;
                            String newGuid = bindGuid(id);
                            Bindings.Bind build = Bindings.Bind.builder().gid(newGuid).createAt(DateUtil.C14()).isDel(0).bindingNo(bindingNo).build();
                            binds.add(build);
                            binding = binds;
                        }

                        String bindFilePath = configCaches.getConfBasePath() + File.separator + corpNo + File.separator + ConfigCaches.BINDINGS_XML;
                        File file = new File(bindFilePath);
                        if (file.exists()) {
                            file.delete();
                        }
                        Bindings bindings = new Bindings();
                        bindings.setBinding(binding);
                        String content = JAXBUtils.obj2Xml(bindings);
                        FileUtil.writeToFile(content, bindFilePath, "UTF-8");

                    } else {
                        //将corpNo加入违规名单
                        if (!violate.contains(corpNo)) {
                            violate.add(corpNo);
                        }
                    }
                }
            }
        }
    }

    /**
     * 必须4位长，从0001开始
     *
     * @param bind
     * @return
     */
    public String bindGuid(Integer bind) {
        if (bind > MAX_SEQ) {
            log.error("最大不能超过9999");
        } else if (bind < 0) {
            log.error("必须大于0！");
        } else {
            String b = bind + "";
            if (b.length() < 4) {
                int appendSize = 4 - b.length();
                for (int i = 0; i < appendSize; i++) {
                    b = "0" + b;
                }
            }
            return b;
        }
        return "";
    }

    private static String genBindNo(String ip, String mac, String corpNo) {
        final String salt = "b9EYglSWrGbsuEYa7Y";
        if (!StringUtil.isBlank(ip) && !StringUtil.isBlank(mac) && !StringUtil.isBlank(corpNo)) {
            String raw = ip + corpNo + salt + mac;
            Digester digester = new Digester("SHA-1");
            return digester.digestHex(raw);

        } else {
            log.error("输入参数不全，无法进行校验！");
            return "";
        }
    }
}
